<?php

namespace app\command;

use core\lib\schema\Schema;
use core\lib\schema\Table;
use hulang\tool\FileHelper;
use PDO;
use phpspirit\databackup\BackupFactory;
use support\Db;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use PhpZip\ZipFile;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use ZipArchive;

class pluginExport extends Command
{
    protected static $defaultName = 'plugin:export';
    protected static $defaultDescription = '打包插件';

    /**
     * @return void
     */
    protected function configure()
    {
        $this->addArgument('name', InputArgument::REQUIRED, 'App plugin name');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $name = $input->getArgument('name'); //打包的插件名
        $output->writeln('正在导出插件' . $name);


        //创建文件夹
        $path = runtime_path() . '/storage/plugin_export/' . $name . '/' . time();
        mkdir($path, 0777, true);
        $this->createSql($name, $path);
        $this->createMenuFile($name, $path);
        $this->createHookFile($name, $path);

        //复制文件夹
        $copydirs = [
            '/template/admin/' . $name,
            '/template/uc/' . $name,
            '/public/static/admin/' . $name,
            '/public/static/uc/' . $name,
            '/plugin/' . $name,
        ];
        foreach ($copydirs as $dir) {
            if (is_dir(base_path() . $dir) && file_exists(base_path() . $dir)) {
                $this->copyDir(base_path() . $dir, $path . '/source/' . $dir);
            }
        }
        $output->writeln('导出插件完成，地址：' . $path);


        return self::SUCCESS;
    }

    /**
     * 生成菜单
     *
     * @param string $name
     * @return void
     */
    protected function createMenuFile(string $name, string $path)
    {
        $menus = Db::table('frame_admin_menu')
            ->where('plugin', '=', $name)
            ->get()
            ->map(function ($value) {
                return (array)$value;
            })
            ->toArray();

        if ($menus) {
            $content = '<?php  return [\'add\' =>' . var_export($menus, true) . '];';

            file_put_contents($path . '/menu.php', $content);
        }


        $menus = Db::table('frame_ucenter_menu')
            ->where('plugin', '=', $name)
            ->get()
            ->map(function ($value) {
                return (array)$value;
            })
            ->toArray();

        if ($menus) {
            $content = '<?php  return [\'add\' =>' . var_export($menus, true) . '];';

            file_put_contents($path . '/ucmenu.php', $content);
        }
    }

    /**
     * 创建钩子文件
     *
     * @param [type] $name
     * @return void
     */
    protected function createHookFile(string $name, string $path)
    {
        $hooks = Db::table('frame_hook')
            ->where('plugin', '=', $name)
            ->get()
            ->map(function ($value) {
                return (array)$value;
            })
            ->toArray();

        if ($hooks) {
            $content = '<?php  return [\'add\' =>' . var_export($hooks, true) . '];';
            file_put_contents($path . '/hook.php', $content);
        }
    }


    protected function createSql($name, $path)
    {


        $conndef = config('database.default');
        $prefix = config('database.connections.' . $conndef . '.prefix');
        $driver = config('database.connections.' . $conndef . '.driver');
        $host = config('database.connections.' . $conndef . '.host');
        $port = config('database.connections.' . $conndef . '.port');
        $database = config('database.connections.' . $conndef . '.database');
        $username = config('database.connections.' . $conndef . '.username');
        $password = config('database.connections.' . $conndef . '.password');


        $tables = Schema::tables();
        $backuptables = [];
        foreach ($tables as $table) {
            if (strpos($table['name'], $prefix . $name . '_') === 0) {
                $backuptables[] = $table['name'];
            }
        }

        if ($backuptables) {
            $pdo =  new PDO($driver . ':host=' . $host . ':' . $port . ';dbname=' . $database, $username, $password, [PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8mb4';"]);
            foreach ($backuptables as $table) {
                $sqlstr = '';
                $sqlstr .= 'DROP TABLE IF EXISTS `' . $table . '`;' . PHP_EOL;
                $rs = $pdo->query('SHOW CREATE TABLE `' . $table . '`');
                $res = $rs->fetchAll();
                $sqlstr .= $res[0][1] . ';' . PHP_EOL;


                $query      = 'select * from `' . $table . '` ';
                $valuers    = $pdo->query($query);
                $valueres   = $valuers->fetchAll(PDO::FETCH_NUM);
                $insertsqlv = '';
                $insertsql  = '';
                if ($valueres) {
                    $insertsql = 'insert into `' . $table . '` VALUES ';
                }

                foreach ($valueres as $v) {
                    $insertsqlv .= ' ( ';
                    foreach ($v as $_v) {
                        $insertsqlv .= (is_null($_v) ? 'NULL' : $pdo->quote($_v)) . ",";
                    }
                    $insertsqlv = rtrim($insertsqlv, ',');
                    $insertsqlv .= ' ),';
                }

                if ($insertsqlv) {
                    $insertsql .= rtrim($insertsqlv, ',') . ' ;' . PHP_EOL;
                }

                $sqlstr .= $insertsql;
                if (file_exists($path . '/install.sql')) {
                    $sqlstr = file_get_contents($path . '/install.sql') . $sqlstr;
                }


                //替换表前缀
                $sqlstr = str_replace('`' . $prefix, '`{{prefix}}', $sqlstr);

                file_put_contents(
                    $path . '/install.sql',
                    $sqlstr
                );
            }
        }
    }




    protected function packFile(string $name, array $dirorfile) {}



    protected   function copyDir($source, $toDir, $force = true)
    {
        // 用于跟踪复制的文件数量
        static $counter = 0;
        // 获取源目录中的文件和子目录列表,排除'.'和'..'
        $paths = array_filter(scandir($source), function ($file) {
            return !in_array($file, ['.', '..']);
        });
        // 遍历源目录中的每个文件和子目录
        foreach ($paths as $path) {
            // 构建源文件或子目录的完整路径
            $sourceFullPath = $source . DIRECTORY_SEPARATOR . $path;
            // 构建目标文件或子目录的完整路径
            $destFullPath = $toDir . DIRECTORY_SEPARATOR . $path;
            // 如果当前项是子目录
            // 拷贝的目标地址如果是不是文件夹,那么说明文件夹不存在,那么首先创建文件夹
            if (is_dir($sourceFullPath)) {
                // 如果目标子目录不存在,则创建它
                if (!is_dir($destFullPath)) {
                    mkdir($destFullPath, 0777, true);
                    chmod($destFullPath, 0755);
                }
                // 递归地复制子目录
                static::copyDir($sourceFullPath, $destFullPath, $force);
                // 继续处理下一个文件或子目录
                continue;
            }
            // 如果不强制覆盖且目标文件已存在,则跳过当前文件
            // 不开启强制覆盖的话如果已经存在文件了那么直接跳过,不进行处理
            if (!$force && file_exists($destFullPath)) {
                continue;
            }
            // 成功复制文件后增加计数器
            if (copy($sourceFullPath, $destFullPath)) {
                $counter++;
            }
        }
        // 返回成功复制的文件数量
        return $counter;
    }
}
